Skip to content

ci(digstore-core): publish the library crate to crates.io - #22

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
ci/digstore-core-cratesio-publish
Jul 16, 2026
Merged

ci(digstore-core): publish the library crate to crates.io#22
MichaelTaylor3d merged 1 commit into
mainfrom
ci/digstore-core-cratesio-publish

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

TLDR

Publishes the digstore-core library crate to crates.io by adding crates.io packaging metadata + a dedicated, idempotent publish workflow. This is WU1 of #680 — the release-first predecessor that unblocks WU2 (dig-urn-resolver's own crates.io publish, a separate later lane). WU2 fails today because dig-urn-resolver git-depends on digstore-core and crates.io forbids git deps; publishing digstore-core by-version is the root fix.

Refs #680 (NOT Closes — WU2 is the dig-urn-resolver side, separate lane).

What changed

  • crates/digstore-core/Cargo.toml — added crates.io-required/recommended [package] metadata: description, repository, readme, keywords, categories. license already inherited from the workspace (GPL-2.0-only). No dependency or code change.
  • crates/digstore-core/README.md — new (referenced by readme =), describes the crate + the .dig format-stability guarantee (§5.1) + features.
  • .github/workflows/publish-crate.yml — new publish workflow (test → package → skip-if-exists → publish).
  • Cargo.toml — workspace version 0.13.30.13.4.

Packaging-only: no code/format behavior change. Per §5.1 the store-format read-crypto and .dig format are untouched.

Trigger design — why it won't collide with nightlies

digstore is a nightlies repo (§3.6): binaries release via nightly-release.yml on a cron/dispatch, and the v* tag fires the binary build (release.yml). Hooking a crate publish to v* or the cron would re-attempt a digstore-core publish on every binary release; crates.io rejects duplicate versions → red runs every night.

Instead the crate publish rides its own tag namespace digstore-core-v* (e.g. digstore-core-v0.13.4) plus workflow_dispatch, and is idempotent: it queries crates.io for the resolved version and no-ops if already published (skip-if-exists, mirroring the nightlies stable skip-if-tagged posture). A re-run or stray duplicate tag never fails red.

Publish flow after merge: bump the workspace version → merge → push digstore-core-vX.Y.Z (or dispatch the workflow) → publishes that version.

Dry-run proof

cargo publish -p digstore-core --dry-run --allow-dirty:

Packaged 45 files, 178.5KiB (48.4KiB compressed)
Verifying digstore-core v0.13.4
...
Compiling digstore-core v0.13.4 (target/package/digstore-core-0.13.4)
Finished dev profile [unoptimized + debuginfo] target(s)
Uploading digstore-core v0.13.4
warning: aborting upload due to dry run

Packages + verifies cleanly: all deps resolve from crates.io, metadata complete, no path/git dep leak (digstore-core has no path/git deps).

Token status

CARGO_REGISTRY_TOKEN is NOT a repo secret on DIG-Network/digstore, and is not on DIG-Network/chia-query either — yet chia-query publishes to crates.io, so it is an org-level secret available to org repos (org secrets propagate unless restricted). The workflow references secrets.CARGO_REGISTRY_TOKEN and fails with a clear error if absent. Action for orchestrator/user: confirm the org CARGO_REGISTRY_TOKEN is scoped to include digstore (or add it) before the first real publish.

SemVer bump rationale

Patch 0.13.3 → 0.13.4: ci/packaging-only, no public API or behavior change (§2.4). Satisfies the version-increment gate (reads [workspace.package].version), and becomes digstore-core's first published version (it inherits version.workspace = true).

Co-Authored-By: Claude noreply@anthropic.com

Add crates.io packaging metadata to `digstore-core` (description, repository,
readme, keywords, categories; license already inherited GPL-2.0-only) and a
dedicated publish workflow so downstream crates (dig-urn-resolver, #680 WU2)
can depend on it BY VERSION instead of via a git dependency crates.io forbids.

The publish rides its OWN tag namespace `digstore-core-v*` (plus dispatch),
NOT the `v*` binary-release tag or the nightly cron, and is idempotent
(skip-if-already-published) so it never re-attempts a duplicate version.

digstore-core has no path/git deps; `cargo publish -p digstore-core --dry-run`
packages and verifies cleanly. Packaging-only — no code/format behavior change
(§5.1 store-format read-crypto unchanged).

Bump workspace version 0.13.3 -> 0.13.4 (patch) to satisfy the
version-increment gate; digstore-core inherits it as its published version.

Refs #680

Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines +36 to +51
name: Test digstore-core
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt -p digstore-core -- --check
- name: Clippy (warnings are errors)
run: cargo clippy -p digstore-core --all-features -- -D warnings
- name: Run tests
run: cargo test -p digstore-core --all-features
- name: Check documentation
run: cargo doc -p digstore-core --no-deps --all-features

publish:
Comment on lines +52 to +103
name: Publish to crates.io
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2

# Package first — proves metadata is complete and no path/git dep leaks, without publishing.
- name: Package (dry check)
run: cargo package -p digstore-core --allow-dirty

# Read the version cargo will publish (the resolved workspace version).
- name: Resolve crate version
id: ver
run: |
V=$(cargo metadata --no-deps --format-version 1 \
| python3 -c 'import sys,json; d=json.load(sys.stdin); print(next(p["version"] for p in d["packages"] if p["name"]=="digstore-core"))')
echo "version=$V" >> "$GITHUB_OUTPUT"
echo "digstore-core version to publish: $V"

# Skip-if-exists: crates.io rejects duplicate versions, so a re-run / stray tag must NO-OP,
# never fail red. Query the crate's versions and stop cleanly if this version is already up.
- name: Skip if version already published
id: exists
run: |
V="${{ steps.ver.outputs.version }}"
# crates.io requires a descriptive User-Agent; 404 => crate not yet published at all.
BODY=$(curl -sS -A "dig-ecosystem-ci (help@dig.net)" \
"https://crates.io/api/v1/crates/digstore-core/versions" || echo '{}')
if echo "$BODY" | python3 -c 'import sys,json; d=json.load(sys.stdin); vs=[v["num"] for v in d.get("versions",[])]; sys.exit(0 if sys.argv[1] in vs else 1)' "$V"; then
echo "digstore-core@$V already on crates.io — skipping publish (no-op)."
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "digstore-core@$V not on crates.io — will publish."
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

- name: Check CARGO_REGISTRY_TOKEN is available
if: steps.exists.outputs.skip == 'false'
run: |
if [ -z "${{ secrets.CARGO_REGISTRY_TOKEN }}" ]; then
echo "::error::CARGO_REGISTRY_TOKEN is not available (repo or org secret)."
echo "Add a crates.io API token as CARGO_REGISTRY_TOKEN (org secret preferred) and re-run."
exit 1
fi

- name: Publish to crates.io
if: steps.exists.outputs.skip == 'false'
run: cargo publish -p digstore-core --allow-dirty --token "$CARGO_REGISTRY_TOKEN"
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
@MichaelTaylor3d
MichaelTaylor3d merged commit ce1cc18 into main Jul 16, 2026
10 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the ci/digstore-core-cratesio-publish branch July 16, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants